<?php

namespace App\Task;

use App\Model\DataAdEcpm;
use App\Model\Payment;
use App\Model\Applet;
use App\Model\SystemOrderRefund;
use Hyperf\DbConnection\Db;
use Hyperf\Logger\LoggerFactory;
use Hyperf\Utils\ApplicationContext;
use Psr\Log\LoggerInterface;
use GuzzleHttp\Client;
class RtecpmTask
{
    protected LoggerInterface $logger;
    //获取token
    public static $getTokenUrl = "https://open.douyin.com/oauth/client_token/";
    //剧目绑定
    public static $ecpmUrl = "https://open.douyin.com/api/traffic/v1/rt_ecpm/query/";


    public static $attributes = ['event_id','mp_id','cost','applet_id','open_id','event_time','created_at','updated_at','user_id','spread_id'];
    public static $updateFields = ['mp_id','cost','applet_id','open_id','event_time','updated_at'];

    public function __construct(protected LoggerFactory $loggerFactory)
    {
        $this->logger = $this->loggerFactory->get('log', 'Rtecpm');
    }

    public function execute()
    {
        try {
            $container = ApplicationContext::getContainer();
            $redis = $container->get(\Hyperf\Redis\RedisFactory::class)->get('default');
            $this->logger->info(date('Y-m-d H:i:s') . '------------------------定时获取广告用户的Ecpm的广告');

            $ecpmKey =  'rt_ecpm_live';
            $keyData = $redis->get($ecpmKey);
            if(!empty($keyData)){
//                $redis->del($orderKey);
                $this->logger->info('存在处理中的ecpm进程');
                $this->logger->info(date('Y-m-d H:i:s') . '------------------------结束定时获取订单进行上报');
                return;
            }else{
                $redis->set($ecpmKey,1);
            }


            $appletData = Applet::query()->where(['id' => 20004,'type' => 2])->select(['id','name','app_id','app_secret'])->first();
            if(!empty($appletData)) {
                $applet_name = $appletData->name;
                $applet_id = $appletData->id;
                //获取token
                $accessToken = $this->getDyAccessToken($appletData->id,$appletData->app_id,$appletData->app_secret);
//                $accessToken = env('DY_TEST_TOKEN');
                if(!empty($accessToken)){

                    //获取用户Ecpm数据
                    $ecpmData = $this->getEcpm($accessToken);
                    if(!empty($ecpmData)){
                        $this->logger->info('获取ecpm成功，数量为：',[count($ecpmData)]);


                        $ecpmchunkData = array_chunk($ecpmData,300);

                        //分组ecpm的数据
                        foreach ($ecpmchunkData as $ecpmInfo){
                            $open_ids = array();
                            $this->logger->info('获取分组ecpm成功，数量为：',[count($ecpmInfo)]);
                            //获取这组ecpm的用户信息
                            foreach ($ecpmInfo as $ecpmtum) {
                                $open_ids[] = $ecpmtum['open_id'];
                            }
                            $open_ids = array_unique($open_ids);
                            //查询对应的用户信息
                            $userData = Db::table('data_user_' . $applet_id)
                                ->whereIn('xc_open_id',$open_ids)
                                ->select(['id','spread_id','xc_open_id'])->get()->toArray();
                            $userOpenIdsKeyVal = array();
                            if(!empty($userData)){
                                foreach ($userData as $userDatum){

                                    $userOpenIdsKeyVal[$userDatum->xc_open_id] = $userDatum;
                                }
                            }
                            $this->logger->info('获取分组ecpm用户，数量为：',[count($userOpenIdsKeyVal)]);
                            foreach ($ecpmInfo as $ecpmtum){

                                $time = date('Y-m-d H:i:s',time());
                                $open_id = $ecpmtum['open_id'];

                                $user_id = 0;
                                $spread_id = 0;
                                if(!empty($userOpenIdsKeyVal[$open_id])){
                                    $user_id = $userOpenIdsKeyVal[$open_id]->id;
                                    $spread_id = $userOpenIdsKeyVal[$open_id]->spread_id;
                                }
                                $insertData[] = [
                                    $ecpmtum['id'],//event_id
                                    $ecpmtum['mp_id'],//mp_id
                                    $ecpmtum['cost'],//cost
                                    $appletData->id,//applet_id
                                    $ecpmtum['open_id'],//open_id
                                    date('Y-m-d H:i:s',$ecpmtum['event_time']),//event_time
                                    $time,//created_at
                                    $time,//updated_at
                                    $user_id,//user_id
                                    $spread_id,//spread_id
                                ];
                            }
                        }
                        $this->logger->info('插入数据，数量为：',[count($insertData)]);
                        if(!empty($insertData)){
                            $attributes = self::$attributes;
                            $attributeArr = [];
                            foreach ($attributes as $attribute){
                                $attributeArr[] = '`'.$attribute.'`';
                            }
                            $attributeArr = implode(',',$attributeArr);
                            $sql = "INSERT INTO data_ad_ecpm (".$attributeArr.") VALUES ";

                            $updateFields = self::$updateFields;
                            $duplicates = [];
                            foreach($updateFields as $updateField){
                                $duplicates[] = "`".$updateField."` = VALUES(`".$updateField."`)";
                            }
                            $duplicatesStr = implode(",",$duplicates);
                            $duplSql = " ON DUPLICATE KEY UPDATE ".$duplicatesStr;
                            $chunkData = array_chunk($insertData,100);
                            foreach ($chunkData as $key  => $insertInfo){
//                                $this->logger->info('插入数据',[count($insertInfo)]);
                                $insertSql = '';
                                foreach ($insertInfo as $insertDatum){
                                    $insertSql .= "(".$this->array_to_string_with_quotes($insertDatum)."),";

                                }
                                $insertSql = rtrim($insertSql, ",");
                                $insertSql = $sql.$insertSql.$duplSql;
                                $insertRes = Db::insert($insertSql);
                                if($insertRes){
                                    $this->logger->info('插入数据执行成功',[count($insertInfo)]);
                                }else{
                                    $this->logger->info('插入数据执行失败',[count($insertInfo)]);
                                }
                            }
                        }
                    }else{
                        $this->logger->error('小程序：'.$applet_name.',没有Ecpm数据');
                    }
                }else{
                    $this->logger->error('小程序:'.$applet_name.' 没有对应的token');
                }
            }else{
                $this->logger->error('小程序不存在');
            }
            $redis->del($ecpmKey);
        }catch (\Exception $e){
            $redis->del($ecpmKey);
            $this->logger->error('请求抖音广告用户的Ecpm的广告接口|错误：' . $e->getLine() . '|' . $e->getMessage());
        }
    }

    function array_to_string_with_quotes($array){
        $result = "";
        foreach($array as $value){
            $result .= '"' . $value . '",';
        }
        $result = rtrim($result, ",");
        return $result;
    }

    public function getEcpm($accessToken,$next_cursor=0,$returnData = array()){

        $params         = [
            "date_hour"   =>date('Y-m-d H',time())
        ];

        if(!empty($next_cursor)){
            $params['cursor'] = $next_cursor;
        }
        $ecpmUrl = self::$ecpmUrl;
//        $this->logger->info('请求广告用户的 ecpm 数据：'.PHP_EOL.var_export(['result' => $params], true));
        $this->logger->info('请求广告用户的 ecpmUrl：'.$ecpmUrl);
        $postResult  = $this->request($params, $ecpmUrl,'POST',$accessToken);
        if($postResult['err_no'] == 0){
//            $this->logger->info('调用广告用户的 ecpm接口成功 返回数据：'.PHP_EOL.var_export(['result' => $postResult], true));
            $resultData = $postResult['data'];
            if(!empty($resultData['records'])){
                $returnData = array_merge($resultData['records'],$returnData);
            }
            if(empty($resultData['next_cursor'])){
                return $returnData;
            }else{
                return $this->getEcpm($accessToken,$resultData['next_cursor'],$returnData);
            }


        }else{
            $this->logger->error('调用广告用户的 ecpm接口失败 返回数据：'.PHP_EOL.var_export(['result' => $postResult], true));
        }
        return false;
    }
    public function getDyAccessToken($applet_id,$app_id,$app_secret){

        $container = ApplicationContext::getContainer();
        $redis = $container->get(\Hyperf\Redis\RedisFactory::class)->get('dy');
        $key = 'dy_admin_access_token';
        $key .= $applet_id;
        $accessToken = $redis->get($key);
        if(empty($accessToken)){
            $params         = [
                'grant_type' => 'client_credential',
                'client_key'    => $app_id,
                'client_secret'   => $app_secret
            ];
            //获取token
            $accessTokenInfo     = $this->request($params, self::$getTokenUrl,'POST');
            if (!empty($accessTokenInfo['data']['access_token'])){
                $accessToken = $accessTokenInfo['data']['access_token'];
                $redis->setex($key,7100,$accessToken);
            }else{
                $accessToken = "";
            }
        }
        $this->logger->info('抖音token为：'.$accessToken);
        return $accessToken;
    }

    /**
     * 传入数组进行HTTP POST请求
     */
    function request(array $params, string $url,string $method,string $access_token = null)
    {
        $client   = new Client([
            'timeout' => 3
        ]);
        $headers       = ['Content-Type' => 'application/json'];
        if(!empty($access_token)){
            $headers['access-token'] = $access_token;
        }

        $requestParams = [
            'headers' => $headers,
        ];
        if ($method == 'GET') {
            $requestParams['query'] = $params;
        } else {
            $requestParams['json'] = $params;//json_encode($params,JSON_UNESCAPED_UNICODE);
        }
        $response = $client->request($method,$url, $requestParams);
        if ($response->getStatusCode() !== 200) {
            return '';
        }
        $result   = $response->getBody()->getContents();
        $resultArr = json_decode($result,true);
        return $resultArr;

    }
}